package fag.core.game.test.asteroids;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;

import fag.core.collision.Collision;
import fag.core.game.AbstractDoodad;
import fag.core.game.AbstractGame;
import fag.core.game.Transformable.Referential;
import fag.core.geometry.Vector2D;

public class Asteroids extends AbstractGame implements KeyListener {
	
	public static void main(String[] args) {
		Asteroids asteroids = new Asteroids();
		asteroids.start();
	}
	
	public static final int WIDTH = 640;
	public static final int HEIGHT = 640;
	private JFrame frame;
	private AsteroidsCamera camera = new AsteroidsCamera();	
	private AsteroidsScene scene = new AsteroidsScene();
	private Vaisseau vaisseau;
	private ArrayList<Missile> missiles = new ArrayList<Missile>();
	private ArrayList<Meteorite> meteorites = new ArrayList<Meteorite>();
	private boolean toucheUp = false, toucheLeft = false, toucheRight = false, toucheSpace = false;
	private int loaderMissile = 0;
	
	Asteroids() {
		camera.setSize(WIDTH, HEIGHT);
		scene.addCamera(camera);
		addScene(scene);
		startAsteroids();
		scene.life = 10;
		
		frame = new JFrame("Asteroids");
		frame.setSize(WIDTH, HEIGHT);
		frame.setResizable(false);
		frame.setVisible(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.add(camera);
		frame.pack();
		frame.addKeyListener(this);
	}
	
	private void startAsteroids() {
		List<AbstractDoodad> l = scene.getDoodads();
		for(AbstractDoodad a : l) {
			scene.removeDoodad(a);
		}
		meteorites.clear();
		missiles.clear();
		vaisseau = new Vaisseau(new VaisseauModel(), new Vector2D(WIDTH / 2, HEIGHT / 2), new Vector2D(0.0, 0.0), 0.0);
		scene.addDoodad(vaisseau);
		Meteorite m = null;
		double random = 0.0;
		for(int i = 0; i < scene.niveau + 2; i++) {
			random = Math.random() * Math.PI * 2;
			m = new Meteorite(new MeteoriteModel(), new Vector2D(), new Vector2D(40 * Math.cos(random), 40 * Math.sin(random)), 0.0, 3);
			m.setAnimation("meteorite_3.png");
			if(random > 0.5) {
				m.setTranslation(WIDTH * Math.random(), 0.0);
			} else {
				m.setTranslation(0.0, HEIGHT * Math.random());
			}
			meteorites.add(m);
			scene.addDoodad(m);
		}
	}

	@Override
	public void step(double dt) {
		if(!camera.gameover) {
			//gestion evenement clavier
			if(toucheUp) {
				Vector2D speed = vaisseau.addSpeed(3.0);
				if(speed.length() < 200.0) {
					vaisseau.setSpeed(speed);
				}
			}
			if(toucheLeft) {
				vaisseau.addRotation(-Math.PI / 64.0);
			}
			if(toucheRight) {
				vaisseau.addRotation(Math.PI / 64.0);
			}
			if(toucheSpace) {
				if(loaderMissile <= 0) {
					Vector2D position = vaisseau.getTranslation();
					position.set(position.add(new Vector2D(Math.cos(vaisseau.getRotation()) * vaisseau.getWidth() / 2.0, Math.sin(vaisseau.getRotation()) * vaisseau.getWidth() / 2.0)));
					Missile m = new Missile(
							new MissileModel(),
							position,
							new Vector2D(300 * Math.cos(vaisseau.getRotation() - Math.PI / 2.0), 300 * Math.sin(vaisseau.getRotation() - Math.PI / 2.0)),
							vaisseau.getRotation());
					missiles.add(m);
					scene.addDoodad(m);
					loaderMissile = 15;
				} else {
					loaderMissile--;
				}
			}
			
			//gestion des collisions
			ArrayList<Missile> removeMissiles = new ArrayList<Missile>();
			ArrayList<Meteorite> removeMeteorites = new ArrayList<Meteorite>();
			ArrayList<Meteorite> addMeteorites = new ArrayList<Meteorite>();
			for(Missile m : missiles) {
				if(m.getTranslationX() < 0 || m.getTranslationX() > WIDTH || m.getTranslationY() < 0 || m.getTranslationY() > HEIGHT) {
					removeMissiles.add(m);
				}
			}
			for(Meteorite me : meteorites) {
				Collision c = me.getHitbox().getCollision(vaisseau.getHitbox());
				if(c.isColliding()) {
					Vector2D normal = c.getNormal();
					Vector2D separator = normal.mul(c.getPenetration() * 1).add(normal);
					vaisseau.translate(separator, Referential.ABSOLUTE);
					vaisseau.bounce(normal.mul(-1.0));
					scene.life--;
					camera.repaint();
				}
				for(Missile m : missiles) {		
					if(m.getHitbox().getCollision(me.getHitbox()).isColliding()) {
						removeMissiles.add(m);
						me.lostOneLife();
						scene.score++;
						camera.repaint();
						if(me.getLife() == 0) {
							removeMeteorites.add(me);
							if(me.getAnimation().getName().equals("meteorite_3.png") || me.getAnimation().getName().equals("meteorite_2.png")) {
								Meteorite new_m = null;
								double random = Math.random() * Math.PI * 2;
								double radian = 0.0;
								for(int i = 0; i < 3; i++) {
									radian = (double)i * 2.0 * Math.PI / 3.0;
									if(me.getAnimation().getName().equals("meteorite_3.png")) {
										new_m = new Meteorite(new MeteoriteModel(), me.getTranslation().clone(), new Vector2D(60 * Math.cos(random + radian), 60 * Math.sin(random + radian)), 0.0, 3);
										new_m.setAnimation("meteorite_2.png");
									} else if(me.getAnimation().getName().equals("meteorite_2.png")) {
										new_m = new Meteorite(new MeteoriteModel(), me.getTranslation().clone(), new Vector2D(90 * Math.cos(random + radian), 90 * Math.sin(random + radian)), 0.0, 3);
										new_m.setAnimation("meteorite_1.png");
									}
									addMeteorites.add(new_m);
								}
							}
						}
					}
				}
			}
			for(Missile m : removeMissiles) {
				scene.removeDoodad(m);
			}
			missiles.removeAll(removeMissiles);
			for(Meteorite m : removeMeteorites) {
				scene.removeDoodad(m);
			}
			meteorites.removeAll(removeMeteorites);
			for(Meteorite m : addMeteorites) {
				scene.addDoodad(m);
			}
			meteorites.addAll(addMeteorites);
			
			//mouvements des objets
			vaisseau.step(dt / 1000);
			if(vaisseau.getTranslationX() < 0) {
				vaisseau.setTranslation(WIDTH + vaisseau.getTranslationX(), vaisseau.getTranslationY());
			} else if(vaisseau.getTranslationX() > WIDTH) {
				vaisseau.setTranslation(vaisseau.getTranslationX() - WIDTH, vaisseau.getTranslationY());
			} else if(vaisseau.getTranslationY() < 0) {
				vaisseau.setTranslation(vaisseau.getTranslationX(), HEIGHT + vaisseau.getTranslationY());
			} else if(vaisseau.getTranslationY() > HEIGHT) {
				vaisseau.setTranslation(vaisseau.getTranslationX(), vaisseau.getTranslationY() - HEIGHT);
			}
			for(Meteorite m : meteorites) {
				m.step(dt / 1000);
				if(m.getTranslationX() < 0) {
					m.setTranslation(WIDTH + m.getTranslationX(), m.getTranslationY());
				} else if(m.getTranslationX() > WIDTH) {
					m.setTranslation(m.getTranslationX() - WIDTH, m.getTranslationY());
				} else if(m.getTranslationY() < 0) {
					m.setTranslation(m.getTranslationX(), HEIGHT + m.getTranslationY());
				} else if(m.getTranslationY() > HEIGHT) {
					m.setTranslation(m.getTranslationX(), m.getTranslationY() - HEIGHT);
				}
			}
			for(Missile m : missiles) {
				m.step(dt / 1000);
			}
			
			if(meteorites.size() == 0) {
				scene.niveau++;
				camera.repaint();
				startAsteroids();
			}
			if(scene.life <= 0) {
				camera.gameover = true;
			}
		}
	}

	@Override
	public void keyPressed(KeyEvent e) {
		if(e.getKeyCode() == KeyEvent.VK_UP) {
			toucheUp = true;
		} else if(e.getKeyCode() == KeyEvent.VK_LEFT) {
			toucheLeft = true;
		} else if(e.getKeyCode() == KeyEvent.VK_RIGHT) {
			toucheRight = true;
		} else if(e.getKeyCode() == KeyEvent.VK_SPACE) {
			toucheSpace = true;
		} else if(e.getKeyCode() == KeyEvent.VK_ENTER) {
			if(camera.gameover) {
				scene.life = 10;
				scene.score = 0;
				scene.niveau = 1;
				camera.repaint();
				startAsteroids();
				camera.gameover = false;
			}
		}
	}
	
	@Override
	public void keyReleased(KeyEvent e) {
		if(e.getKeyCode() == KeyEvent.VK_UP) {
			toucheUp = false;
		} else if(e.getKeyCode() == KeyEvent.VK_LEFT) {
			toucheLeft = false;
		} else if(e.getKeyCode() == KeyEvent.VK_RIGHT) {
			toucheRight = false;
		} else if(e.getKeyCode() == KeyEvent.VK_SPACE) {
			toucheSpace = false;
		}
	}

	@Override
	public void keyTyped(KeyEvent e) {}
	
}
